import { Reducer } from "redux";
import { cloneDeep } from "lodash-es";
import { ADD_CMS_COMPONENT, DELETE_CMS_NODE, SET_CMS_CURRENT_NODE, SET_CMS_NODE_PROPS, UPDATE_CMS_COMPONENT, SET_CMS_NODE_BASE_PROPS } from "store/constants";
import { IAction } from "../type";

export interface ITemplate {
    id: string;
    component: string;
    props: {[key: string]: any};
    children: ITemplate[];
    compTitle?: string;
}

export interface IState {
    config: ITemplate[],
    currentNode: string | string[];  // 如果是string，就是最外层的元素，如果是字符串数组，则是嵌套的内层元素
}

const defaultHomeState: IState = {
    config: [],
    currentNode: ""
}

const cmsReducer: Reducer<IState, IAction> = (state = defaultHomeState, action) => {
    switch(action.type){
        case ADD_CMS_COMPONENT:
            const { wrapper = false } = action.payload || {};
            const oldConfig = state.config;
            if(wrapper){
                return {
                    ...state,
                    config: [...oldConfig, action.payload?.config]
                }
            }
            if(state.currentNode !== ""){
                const current = Array.isArray(state.currentNode) ? state.currentNode[0] : state.currentNode;
                const wrapperNodeIndex = oldConfig.findIndex(item => item.id === current);
                if(wrapperNodeIndex !== -1){
                    oldConfig.splice(wrapperNodeIndex, 1, {
                        ...oldConfig[wrapperNodeIndex],
                        children: [...oldConfig[wrapperNodeIndex].children, action.payload?.config]
                    })
                    return {
                        ...state,
                        config: [...oldConfig]
                    }
                }
                return state;
            }
            return state;
        case SET_CMS_CURRENT_NODE:
            return {
                ...state,
                currentNode: action.payload
            }
        case SET_CMS_NODE_PROPS:
            const { currentNode, config } = state;
            if(!Array.isArray(currentNode)){
                const nodeIndex = config.findIndex(item => item.id === currentNode);
                if(nodeIndex !== -1) config[nodeIndex] = {
                    ...config[nodeIndex],
                    props: {
                        ...config[nodeIndex]?.props,
                        ...action.payload
                    }
                }
                return {
                    ...state,
                    config: [...config]
                }
            }
            const node = currentNode.reduce((prev: any, cur: any, index: number) => {
                if(!prev) return {};
                const node = prev.find((item: any) => item.id === cur);
                if(!node) return null;
                return index === currentNode.length - 1 ? node : node.children || node;
            }, config);
            if(node){
                node.props = {
                    ...node.props,
                    ...action.payload
                }
                return {
                    ...state,
                    config: cloneDeep(config)
                }
            }
            return state;
        case SET_CMS_NODE_BASE_PROPS:
            const rootNodeId = !Array.isArray(state.currentNode) ? state.currentNode : state.currentNode?.[0];
            const nodeIndex = state.config.findIndex(item => item.id === rootNodeId);
            if(nodeIndex !== -1) state.config[nodeIndex] = {
                ...state.config[nodeIndex],
                ...action.payload
            }
            return {
                ...state,
                config: [...state.config]
            }
        case UPDATE_CMS_COMPONENT:
            return {
                ...state,
                config: action.payload
            }
        case DELETE_CMS_NODE:
            if(!state.currentNode || state.currentNode === "") return state;
            if(Array.isArray(state.currentNode)){
                let node: ITemplate | undefined = undefined;
                let list = state.config;
                for(let idx = 0; idx < state.currentNode.length; idx++){
                    node = list.find(item => item.id === state.currentNode[idx]);
                    if(!node) break;
                    if(idx !== state.currentNode.length - 1) list = node.children;
                }
                if(!node) return state;
                if(Array.isArray(list)){
                    const index = list.findIndex(item => item.id === (node as ITemplate).id);
                    if(index !== -1) list.splice(index, 1)
                }
            } else {
                const index = state.config.findIndex(item => item.id === state.currentNode);
                state.config.splice(index, 1);
            }
            return {
                ...state,
                currentNode: "",
                config: cloneDeep(state.config)
            }
        default:
            return state;
    }
}

export default cmsReducer;